package com.hernandez.games.adventures.controllers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.hernandez.games.adventures.Utils;
import com.hernandez.games.adventures.events.IEventHandler;
import com.hernandez.games.adventures.events.IEvent;

public class EventController implements IController {
	private static final Logger LOG = Logger.getLogger(EventController.class.getSimpleName());
	private static final EventController INSTANCE = new EventController();
	private static final Map<Class<? extends IEvent>, List<? extends IEventHandler<? extends IEvent>>> classMap =
		new HashMap<Class<? extends IEvent>, List<? extends IEventHandler<? extends IEvent>>>();
	private EventController() {}
	
	private void registerEvent(Class<? extends IEvent> newClass) {
		if(!classMap.containsKey(newClass))
			classMap.put(newClass, new ArrayList<IEventHandler<? extends IEvent>>());
	}
	
	public <T extends IEventHandler<? extends IEvent>> void registerHandler(Class<? extends IEvent> newClass, T eventCallback) {
		Utils.checkNull(newClass); Utils.checkNull(eventCallback);
		registerEvent(newClass);
		List<T> eventList = (List<T>) classMap.get(newClass);
		eventList.add(eventCallback);
	}
	
	public <T extends IEvent> void publishEvent(T event) {
		Utils.checkNull(event);
		Class<? extends IEvent> eventClass = event.getClass();
		registerEvent(eventClass);
		List<? extends IEventHandler<T>> handlers = (List<? extends IEventHandler<T>>) classMap.get(eventClass);
		String newLine = System.getProperty("line.separator");
		StringBuilder buff = new StringBuilder("Event '").append(eventClass.getSimpleName()).append("' is gonna be published to: ").append(newLine);
		for(IEventHandler<T> eventCallback : handlers) {
			buff.append(eventCallback.getClass().getSimpleName()).append(newLine);
			eventCallback.publishEvent(event);
		}
		LOG.info(buff.toString());
	}
	
	public static EventController getInstance() {
		return INSTANCE;
	}
}
